package com.zzzzzz.account.user;

import java.util.List;

import javax.annotation.Resource;

import org.apache.shiro.authc.credential.PasswordService;
import org.bson.types.ObjectId;
import org.springframework.stereotype.Repository;

import com.google.code.morphia.query.Query;
import com.google.code.morphia.query.UpdateOperations;
import com.mongodb.MongoException;
import com.zzzzzz.common.util.StringPool;
import com.zzzzzz.core.dao.morphia.BaseDao;

@Repository("userDao")
public class UserDaoImpl extends BaseDao implements UserDao {

	@Resource
	private PasswordService passwordService;
	
	@Override
	public void add(User user) throws UserAlreadyExistsException {
		try{
			user.setStatus(1);
			user.setPassword(passwordService.encryptPassword(user.getPassword()));
			db.save(user);
			
			//同時更新userbase
			addUserBase(user);
		}catch(MongoException.DuplicateKey e){
			throw new UserAlreadyExistsException(user.getEmail());
		}
	}
	
	private void addUserBase(User user) throws UserAlreadyExistsException {
		UserBase userBase = new UserBase();
		userBase.setUserId(ObjectId.massageToObjectId(user.getUserId()));
		userBase.setUsername(user.getUsername());
		userBase.setThumbnailId(user.getThumbnailId());
		db.save(userBase);
	}
	
	@Override
	public User findByEmail(String email) throws NoSuchUserException {
		User user = db.find(User.class, "email", email).get();
		if(user == null) {
			throw new NoSuchUserException();
		}
		return user;
	}
	
	public Boolean isEmailExisting(String email) {
		try {
			this.findByEmail(email);
		} catch (NoSuchUserException e) {
			return false;
		}
		return true;
	}
	
	@Override
	public User findById(String userId) {
		return db.find(User.class, "_id", ObjectId.massageToObjectId(userId)).get();
	}

	@Override
	public UserBase findUserBaseById(String userId) {
		return db.find(UserBase.class, "_id", ObjectId.massageToObjectId(userId)).get();
	}
	
	@Override
	public void editStatus(String userId, Integer status) {
		Query<User> query = db.createQuery(User.class);
		query.filter("_id", ObjectId.massageToObjectId(userId));
		db.update(query, db.createUpdateOperations(User.class).set("status", status));
	}
	
	@Override
	public void editPassword(String userId, String password) {
		
		String newPassword = passwordService.encryptPassword(password);
		
		Query<User> query = db.createQuery(User.class);
		query.filter("_id", ObjectId.massageToObjectId(userId));
		db.update(query, db.createUpdateOperations(User.class).set("password", newPassword));
	}
	
	@Override
	public void editProfile(String userId, String username, String aboutMe) {
		Query<User> query = db.createQuery(User.class);
		query.filter("_id", ObjectId.massageToObjectId(userId));
		UpdateOperations<User> updateOperations = db.createUpdateOperations(User.class);
		updateOperations.set("username", username)
						.set("aboutMe", aboutMe);
		db.update(query, updateOperations);
		
		editUserBaseProfile(userId, username);
	}
	
	private void editUserBaseProfile(String userId, String username) {
		Query<UserBase> query = db.createQuery(UserBase.class);
		query.filter("_id", ObjectId.massageToObjectId(userId));
		db.update(query, db.createUpdateOperations(UserBase.class)
				.set("username", username)
		);
	}

	@Override
	public void editEmail(String userId, String email) {
		Query<User> query = db.createQuery(User.class);
		query.filter("_id", ObjectId.massageToObjectId(userId));
		db.update(query, db.createUpdateOperations(User.class)
				.set("email", email)
		);
	}
	
	@Override
	public void editPortrait(String userId, String portraitId) {
		Query<User> query = db.createQuery(User.class);
		query.filter("_id", ObjectId.massageToObjectId(userId));
		db.update(query, db.createUpdateOperations(User.class)
				.set("portraitId", portraitId)
		);
	}
	
	@Override
	public void editThumbnail(String userId, String thumbnailId) {
		Query<User> query = db.createQuery(User.class);
		query.filter("_id", ObjectId.massageToObjectId(userId));
		db.update(query, db.createUpdateOperations(User.class)
				.set("thumbnailId", thumbnailId)
		);
		
		//同時更新userbase
		editUserBaseThumbnail(userId, thumbnailId);
	}
	
	private void editUserBaseThumbnail(String userId, String thumbnailId) {
		Query<UserBase> query = db.createQuery(UserBase.class);
		query.filter("_id", ObjectId.massageToObjectId(userId));
		db.update(query, db.createUpdateOperations(UserBase.class)
				.set("thumbnailId", thumbnailId)
		);
	}
	
	@Override
	public List<User> findAll(int start, int offset, boolean ascending) {
		Query<User> query = db.createQuery(User.class);
		String condition = "createDate";
		if(!ascending) {
			condition = StringPool.DASH + condition;
		}
		query.limit(offset).offset(start).order(condition);
		return query.asList();
	}
	
}